package com.lagou.java;


import com.google.common.collect.Lists;
import com.lagou.java.service.UserService;
import io.netty.bootstrap.Bootstrap;
import io.netty.channel.Channel;
import io.netty.channel.ChannelFuture;
import io.netty.channel.EventLoopGroup;
import lombok.extern.slf4j.Slf4j;
import sun.rmi.runtime.Log;

import javax.sound.sampled.Line;
import javax.xml.ws.Service;
import java.nio.file.Path;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.TimeUnit;
import java.util.logging.Filter;
import java.util.stream.Collectors;

import static com.lagou.java.ZkBoostrap.remoteServiceAddresses;

/**
 * @Classname ClientBootstrap
 * @Description TODO
 * @Date 2020/7/22 19:42
 * @Created by pc
 */
@Slf4j
public class ClientBootstrap {

    // 存放所有的远程地址, 支持多客户端和多服务端
    public volatile static Map<AddressInfo, ClientInfo> addressesWithHandlers = new ConcurrentHashMap<>();


    public static void main(String[] args) throws InterruptedException {
        String zkAddress = "127.0.0.1:2181";
        //        // 初始化 zookeeper
        ArrayList<String> clients = Lists.newArrayList(RpcConsumer.getClientName()
                , RpcConsumer.getClientName());
        new ZkBoostrap(zkAddress, clients);

        while (true) {

            // ===============================作业一开始==================================
            // 作业一 ：在基于Netty的自定义RPC的案例基础上，进行改造。基于Zookeeper实现简易版服务的注册与发现机制
//            addressesWithHandlers.entrySet().forEach(entry -> {
//                ClientInfo clientInfo = entry.getValue();
//                if (clientInfo.channelFuture != null) {
//                    Channel channel = clientInfo.channelFuture.channel();
//                    // 若客户端与远程的连接可用， 则直接发送消息， 否则跳过
//                    if (channel.isActive() && clientInfo.userService != null ) {
//                        System.out.println("====>> 服务端: " + channel.remoteAddress().toString().substring(1)
//                                + "--本地地址：" + channel.localAddress().toString().substring(1)
//                                + ">>>" + entry.getKey().localClientName
//                                + "返回信息 ： " + clientInfo.userService.sayHello("hello : " + new Date()));
//                    } else {
//                        System.out.println("====>> 服务端: " + channel.remoteAddress().toString().substring(1)
//                                + "--本地地址：" + channel.localAddress().toString().substring(1)
//                                + ">>>" + entry.getKey().localClientName
//                                + "连接中断, 无法发送消息");
//                    }
//
//                    try {
//                        TimeUnit.SECONDS.sleep(2);
//                    } catch (InterruptedException e) {
//                        e.printStackTrace();
//                    }
//                }
//            });

            // ===============================作业二结束==================================

            // ===============================作业二开始==================================
            // 作业二 ： 实现基于Zookeeper的简易版负载均衡策略
            ServerInfo availableService = null;
            for (ServerInfo service : remoteServiceAddresses) {
                if (availableService == null) {
                    availableService = service;
                } else {
                    int i = availableService.compareTo(service);
                    // 随机取服务端
                    if (i == 0) {
                        log.info("");
                        availableService = new Random().nextInt(10) % 2 == 0 ? availableService : service;
                    }
                    // 取响应时间较近的服务
                    availableService = i > 0 ? availableService : service;
                }

            }
            ServerInfo service = availableService;
            log.info("===>>>>当前优先的远程服务端为： {}, 所有服务端信息为：{}", availableService, remoteServiceAddresses.toString());
            addressesWithHandlers.entrySet()
                    .stream()
                    .filter(entry -> entry.getKey().remoteAdress.equals(service.getAddress()))
                    .forEach(entry -> {
                        ClientInfo clientInfo = entry.getValue();
                        if (clientInfo.channelFuture != null) {
                            Channel channel = clientInfo.channelFuture.channel();
                            // 若客户端与远程的连接可用， 则直接发送消息， 否则跳过
                            if (channel.isActive() && clientInfo.userService != null ) {
                                System.out.println("====>> 服务端: " + channel.remoteAddress().toString().substring(1)
                                        + "--本地地址：" + channel.localAddress().toString().substring(1)
                                        + ">>>" + entry.getKey().localClientName
                                        + "返回信息 ： " + clientInfo.userService.sayHello("hello : " + new Date()));
                            } else {
                                System.out.println("====>> 服务端: " + channel.remoteAddress().toString().substring(1)
                                        + "--本地地址：" + channel.localAddress().toString().substring(1)
                                        + ">>>" + entry.getKey().localClientName
                                        + "连接中断, 无法发送消息");
                            }

                        }
                    });
//
        // ===============================作业二结束=================================
//
            System.out.println("========================结束 loop============================");
            TimeUnit.SECONDS.sleep(2);
        }

//

    }

    // 地址信息
    public static class AddressInfo {
        // 客户端名称
        public String localClientName;
        // 客户端地址
        public String localAddress;
        // 服务地址
        public String remoteAdress;

        public AddressInfo(String localClientName, String remoteAdress) {
            this.localClientName = localClientName;
            this.remoteAdress = remoteAdress;
        }

        public Boolean hasRemoteAddress(String host, int port) {
            if(this.remoteAdress == null || this.remoteAdress.trim().equals("")) return false;
            return this.remoteAdress.equals(host.trim() + ":" + port);
        }

        @Override
        public int hashCode() {
            return (this.remoteAdress+this.localClientName).hashCode();
        }

        @Override
        public boolean equals(Object obj) {
            if(obj == null || !(obj instanceof AddressInfo)) return false;
            AddressInfo addressInfo = (AddressInfo) obj;
            if (addressInfo.localClientName.equals(this.localClientName) && addressInfo.remoteAdress.equals(this.remoteAdress)) {
                return true;
            }
            return false;
        }

        public boolean equals(String localClientName, String remoteAdress) {
            if(localClientName == null || remoteAdress == null) return false;
            if (localClientName.equals(this.localClientName) && remoteAdress.equals(this.remoteAdress)) {
                return true;
            }
            return false;
        }
    }

    // 客户端信息
    public static class ClientInfo<T> {

        public EventLoopGroup group;

        public UserClientHandler userClientHandler;

        public UserService userService;

        public ChannelFuture channelFuture;

        public Bootstrap bootstrap;


        public ClientInfo() {
        }


    }


}
